package controllers;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import models.Eentity;
import models.Idea;
import models.Organization;
import models.Plan;
import models.Request;
import models.Role;
import models.Tag;
import models.Topic;
import models.User;
import notifiers.Mails;

import org.apache.commons.mail.EmailException;

import play.data.validation.Email;
import play.data.validation.Required;
import play.mvc.Controller;

public class Application extends Controller {

	public static void c2() {
		render();
	}

	public static void index() {
//testing a commit
		List<Organization> organizations = Organization.findAll();
		String username = Security.connected();
		User user = User.findByUsername(username);
		render(organizations, user);
	}

	/**
	 * Remove the entities belong to secret organization
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0428
	 * @category C4S6
	 * @params List <Entity> l: The list of entities returned form search
	 */

	public static void filterSecretEntity(List<Eentity> l) {
		for (int i = 0; i < l.size(); i++) {

			if (l.get(i).getOrganization().getPrivacy().equals("secret")) {
				l.remove(i);
				i--;
			}

		}

	}

	/***
	 * Remove Entities, Topics and organization from a search result that
	 * belongs to any secret organization in one method
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0502
	 * @category C4S6
	 * @params List <Object> l: the search results
	 * @return List <Object> l: the modified search result after filtering
	 */
	public static List filterSecret(List<Object> l) {
		for (int i = 0; i < l.size(); i++) {
			if (l.size() > 0 && l.get(i) instanceof Eentity) {
				Eentity e = (Eentity) l.get(i);
				if (e.getOrganization().getPrivacy().equalsIgnoreCase("secret")) {
					l.remove(i);
				}
			}
			if (l.size() > 0 && l.get(i) instanceof Topic) {
				Topic t = (Topic) l.get(i);
				if (t.getOrganization().getPrivacy().equalsIgnoreCase("secret")) {
					l.remove(i);
				}
			}
			if (l.size() > 0 && l.get(i) instanceof Organization) {
				Organization o = (Organization) l.get(i);
				if (o.getPrivacy().equalsIgnoreCase("secret")) {
					l.remove(i);
				}

			}
			if (l.size() > 0 && l.get(i) instanceof Idea) {
				Idea idea = (Idea) l.get(i);
				if (idea.getOrganization() != null)
			
				if (idea.getOrganization().getPrivacy().equalsIgnoreCase("secret")) {
					l.remove(i);
				}

			}

		}
		return l;

	}

	/***
	 * Remove the topics belong to secret organization
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0428
	 * @category C4S6
	 * @params List <Topic> l: The list of entities returned form search
	 */
	public static void filterSecretTopic(List<Topic> l) {
		for (int i = 0; i < l.size(); i++) {

			if (l.get(i).getOrganization().getPrivacy().equals("secret")) {
				l.remove(i);
				i--;
			}

		}

	}

	/**
	 * Remove the secret organization
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0428
	 * @category C4S6
	 * @params List <Organization> l: The list of entities returned form search
	 */
	public static List filterSecretOrganization(List<Organization> l) {
		for (int i = 0; i < l.size(); i++) {
			// editied the getType to getPrivacy_IK
			if (l.get(i).getPrivacy().equals("secret")) {
				l.remove(i);
				i--;
			}

		}
		return l;

	}

	/**
	 * Filter by request only
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0429
	 * @category C4S3
	 * @params List <Object> l: The list of objects returned form search result
	 * @return ArrayList: of Requests.
	 */

	public static SearchResult filterByRequest(SearchResult l) {
		SearchResult r = new SearchResult();
		r.setRequests(l.getRequests());
		return  r;
	}

	/**
	 * Filter by idea only
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0429
	 * @category C4S3
	 * @params List <Object> l: The list of objects returned form search result
	 * @return ArrayList: of Ideas
	 */
	public static SearchResult filterByIdea(SearchResult l) {
		SearchResult r = new SearchResult();
		r.setIdeas(l.getIdeas());
		return  r;
	}

	/**
	 * Filter by plan only
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0429
	 * @category C4S3
	 * @params List <Object> l: The list of objects returned form search result
	 * @return ArrayList: of plans
	 */

	public static SearchResult filterByPlan(SearchResult l) {
		SearchResult r = new SearchResult();
		r.setPlans(l.getPlans());
		
		return  r;

	}

	/**
	 * 
	 * method that send an email sharing a plan/request/idea calls Mails.show
	 * from the notifier package
	 * 
	 * @author Amr Draz
	 * @version 2011.0503
	 * @category C4S9
	 * @parameter sender: the person sharing email: the mail that is being shared too
	 * 			  emailTo: The email that this link should be shared with
	 *            content: a message the sender includes
	 *            path: the url to the shared idea/plan/request
	 * @return none
	 */

	public static void share(String sender, @Email @Required String emailTo,
			@Required String content, String path) throws EmailException {

		/*
		 * SimpleEmail email = new SimpleEmail();
		 * 
		 * email.setHostName("smtp.gmail.com"); email.setSmtpPort(587);
		 * email.setTLS(true); email.setFrom("noreply@gmail.com");
		 * email.setSubject(((sender == null)?"someone":sender)
		 * +" wanted to share this with you"); content = sender
		 * +" sent you this message, \n\n" + content + "\n\n see " + path;
		 * email.setMsg(content); email.addTo(emailTo); email.send();
		 */

		Mails.share(sender, emailTo, content, path);

		index();
	}

	/**
	 * a method that gets all inactive ideas for a specific idea developer
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0502
	 * @category C4S18
	 * 
	 */

	public static void getInactiveIdea() {
		String name = session.get("username");
		User s = User.findByUsername(name);
		System.out.println(s.getUsername());
	System.out.println(s.getRoleList().get(0).getTitle());
		List<Role> role = s.getRoleList();
		List<Idea> idea;
		LinkedList inactiveIdea = new LinkedList();
		for (int i = 0; i < role.size(); i++) {
			if (role.get(i).getTitle().equalsIgnoreCase("Ideas' Developer")) {
				idea = s.getIdeaList();
				for (int j = 0; j < idea.size(); j++) {
					if (!(idea.get(j).isActivityStatus())
							&& !(idea.get(j).isDraft())) {
						inactiveIdea.addLast(idea.get(j));
					}
				}

			}
		}

		render(inactiveIdea);

	}

	/**
	 * a method that gets all inactive ideas
	 * 
	 * @author Michael Ibraam
	 * @version 2011.0502
	 * @category C4S18
	 * 
	 */

	public static void notifyIfInactive() {

		List<Idea> l = Idea.findAll();
		LinkedList<User> u = null;

		/*
		 * for (int i = 0; i < l.size(); i++) { if (l.get(i).isDraft()) {
		 * l.remove(i); i--; } }
		 */

		for (int i = 0; i < l.size(); i++) {
			if (!l.get(i).isActivityStatus()) {
				u.addAll(l.get(i).getCreators());

			}
			for (int j = 0; j < u.size(); j++) {
				User user = u.get(i);
				String subject = "Inactive Idea Notification";
				String content = "Idea with title " + l.get(i).getTitle()
						+ "is Inactive";
				try {
					user.sendNotification(user, subject, content);
					System.out.println("Notification sent");
				} catch (EmailException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}
		/*
		 * for (int i = 0; i < u.size(); i++) { User user = u.get(i); String
		 * subject = "you have inactive idea"; String content = ""; try {
		 * user.sendNotification(user, subject, content); } catch
		 * (EmailException e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); } }
		 */

	}

	/**
	 * 
	 * this method searches the db for stuff which it then returns and render in
	 * search.html
	 * 
	 * @author Amr Draz
	 * @version 2011.0503
	 * @category C4S2
	 * @parameter query: the query to be searched orID: the id of the
	 *            organization in case by context
	 * @return none
	 */

	public static void quickSearch(@Required String query, long orgId) {

		if (validation.hasErrors()) {
			flash.error("Oops, you need to enter some text to search!");
			index();
		}

		query = query.toLowerCase();
		query = escapeHTML(query);
		query = escapeSQL(query);

		SearchResult result = search(query);
		if (orgId != 0) {
			System.out.println("you are now searching by context on org id: " + orgId);
			filterByContext(result, orgId);
		}

		List<Long> ideasID = new LinkedList<Long>();
		for (int i = 0; i < result.ideas.size(); i++)
			ideasID.add(result.ideas.get(0).getId());
		render("application/search.html", result, ideasID);

	}

	/**
	 * 
	 * this method where the actual search happens
	 * 
	 * @author Amr Draz
	 * @version 2011.0503
	 * @category C4S2
	 * @parameter query: the query to be searched orID: the id of the
	 *            organization in case by context
	 * @return List<Idea>: the list of all ideas found
	 */

	public static SearchResult search(String query) {

		SearchResult result = new SearchResult();

		String[] tokens = query.split(" ");

		List<Idea> ideas = null;
		query = "select m from Idea m where LOWER(m.title) like '%" + tokens[0]
				+ "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.title) like '%" + tokens[i] + "%' ";
		}
		result.setIdeas(filterSecret(Idea.find(query).fetch()));

		query = "select m from Organization m where LOWER(m.name) like '%"
				+ tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.name) like '%" + tokens[i] + "%' ";
		}
		result.setOrganizations(filterSecret(Organization.find(query).fetch()));

		query = "select m from Topic m where LOWER(m.title) like '%"
				+ tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.title) like '%" + tokens[i] + "%' ";
		}
		result.setTopics(filterSecret(Topic.find(query).fetch()));

		query = "select m from Eentity m where LOWER(m.name) like '%"
				+ tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.name) like '%" + tokens[i] + "%' ";
		}
		result.setEntities(filterSecret(Eentity.find(query).fetch()));
		
		query = "select m from Plan m where LOWER(m.name) like '%"+tokens[0]+"%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.name) like '%"+tokens[i]+"%' ";
		}		
		result.setPlans(filterSecret(Plan.find(query).fetch()));
		
		query = "select m from Request m where LOWER(m.title) like '%"+tokens[0]+"%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.title) like '%"+tokens[i]+"%' ";
		}		
		result.setRequests(filterSecret(Request.find(query).fetch()));

		return result;

	}

	/*public static SearchResult searchByContext(String query, long orgId) {

		SearchResult result = new SearchResult();

		String[] tokens = query.split(" ");

		query = "select m from Idea m, Organization o where m.id = " + orgId
				+ " And ( LOWER(m.title) like '%" + tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.title) like '%" + tokens[i] + "%' ";
			result.ideas = filterSecret(Idea.find(query).fetch());
		}
		query += " )";
		query = "select m from Organization m, Organization o where o.id = "
				+ orgId + " And ( LOWER(m.name) like '%" + tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.name) like '%" + tokens[i] + "%' ";
		}
		query += " )";
		result.organizations = filterSecret(Organization.find(query).fetch());

		query = "select m from Topic m, Organization o where o.id = " + orgId
				+ " And ( LOWER(m.title) like '%" + tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.title) like '%" + tokens[i] + "%' ";
		}
		query += " )";
		result.topics = filterSecret(Topic.find(query).fetch());

		query = "select m from Eentity m, Organization o where o.id = " + orgId
				+ " And (LOWER(m.name) like '%" + tokens[0] + "%' ";
		for (int i = 1; i < tokens.length; i++) {
			query += " OR LOWER(m.name) like '%" + tokens[i] + "%' ";
		}
		query += " )";
		result.entities = filterSecret(Eentity.find(query).fetch());

		return result;
	}*/

	/**
	 * get entities or topics that belong to the organization the user is
	 * browsing
	 * 
	 * @author Michael Ibraam
	 * @version 2011.05
	 * @category C4S7
	 * @param List
	 *            <Object> e: The list of objects returned form search result
	 * @param long orgId : the returned id of the organization the user is
	 *        browsing from the view
	 * @param searchResult r : the returned Search Results
	 * @return searchResult :  the new searchResults
	 */


	public static SearchResult filterByContext(SearchResult r, long orgId) {
		
		for(int i=0;i<r.getEntities().size();i++){
		if(r.getEntities().get(i).getOrganization().getId() != orgId)
		{
			r.getEntities().remove(i);

		}
		if(r.getTopics().get(i).getOrganization().getId() == orgId){
			r.getTopics().remove(i);
		}
		if(r.getIdeas().get(i).getOrganization().getId() == orgId){
			r.getTopics().remove(i);
		}
		
		
		
	}

		return r;
	}
		


	/**
	 * Browses through tags, returning a list of all tag names present in the
	 * system
	 * 
	 * @author Arwa Ismail
	 * @version 2010.0503
	 * @category C4S4
	 */

	public static void browseTags() {
		List<Tag> allTags = Tag.findAll();
		List<String> tagNames = new LinkedList<String>();

		for (int i = 0; i < allTags.size(); i++)
			tagNames.add(allTags.get(i).getName());
		render(tagNames);
	}

	/**
	 * Browses through entities, returning a list of all entity names present in
	 * the system that are neither private nor secret.
	 * 
	 * @author Arwa Ismail
	 * @version 2010.0503
	 * @category C4S5
	 */
		public static void browseEntities() {
		List<Eentity> allEentities = Eentity.findAll();
		List<String> entityNames = new LinkedList<String>();

		for (int i = 0; i < allEentities.size(); i++)
		{
			if(!allEentities.get(i).getOrganization().getPrivacy().equalsIgnoreCase("private") || !allEentities.get(i).getOrganization().getPrivacy().equalsIgnoreCase("secret"))
			entityNames.add(allEentities.get(i).getName());
		
		}
		render(entityNames);
	}

	/**
	 * 
	 * A method that escapes HTML special characters such as ' % _ &
	 * 
	 * @author Amr Draz
	 * @version 2011.05.05
	 * @category C4S2
	 * @parameter s: the String to be escaped
	 * @return String: an escaped String
	 */

	public static String escapeHTML(String s) {
		String escaped = "";
		int n = s.length();
		for (int i = 0; i < n; i++) {
			char c = s.charAt(i);
			switch (c) {
			case '<':
				escaped += "&lt;";
				break;
			case '>':
				escaped += "&gt;";
				break;
			case '&':
				escaped += "&amp;";
				break;
			case '"':
				escaped += "&quot;";
				break;
			/*case 'à':
				escaped += "&agrave;";
				break;
			case '�':
				escaped += "&Agrave;";
				break;
			case 'â':
				escaped += "&acirc;";
				break;
			case 'ä':
				escaped += "&auml;";
				break;
			case 'Ä':
				escaped += "&Auml;";
				break;
			case 'å':
				escaped += "&aring;";
				break;
			case 'Å':
				escaped += "&Aring;";
				break;
			case 'æ':
				escaped += "&aelig;";
				break;
			case 'Æ':
				escaped += "&AElig;";
				break;
			case 'ç':
				escaped += "&ccedil;";
				break;
			case 'Ç':
				escaped += "&Ccedil;";
				break;
			case 'é':
				escaped += "&eacute;";
				break;
			case 'è':
				escaped += "&egrave;";
				break;
			case 'ê':
				escaped += "&ecirc;";
				break;
			case 'ë':
				escaped += "&euml;";
				break;
			case 'Ë':
				escaped += "&Euml;";
				break;
			case 'ô':
				escaped += "&ocirc;";
				break;
			case 'ö':
				escaped += "&ouml;";
				break;
			case 'Ö':
				escaped += "&Ouml;";
				break;
			case 'ø':
				escaped += "&oslash;";
				break;
			case 'Ø':
				escaped += "&Oslash;";
				break;
			case 'ß':
				escaped += "&szlig;";
				break;
			case 'ù':
				escaped += "&ugrave;";
				break;
			case 'û':
				escaped += "&ucirc;";
				break;
			case 'ü':
				escaped += "&uuml;";
				break;
			case 'Ü':
				escaped += "&Uuml;";
				break;
			case ' ':
				escaped += "&nbsp;";
				break;
*/
			default:
				escaped += c;
				break;
			}
		}
		return escaped;
	}

	/**
	 * 
	 * A method that escapes SQL regex such as ' % _ &
	 * 
	 * @author Amr Draz
	 * @version 2011.05.05
	 * @category C4S2
	 * @parameter s: the String to be escaped
	 * @return String: an escaped String
	 */

	public static String escapeSQL(String s) {
		s = s.replace("'", "''");
		s = s.replace("%", "\\%");
		s = s.replace("_", "/_");
		s = s.replace("&", "\\&");
		return s;
	}

	/**
	 * Success page (to be used when redirecting from a form
	 * 
	 * @author Youssef Selim
	 * @version 2010.0505
	 */
	public static void success() {
		render();
	}

	/**
	 * Method export(List<long> ideas) takes a list of ideas IDs and exports it
	 * to csv
	 * 
	 * @author Nader Alexan
	 * @version 2010.0505
	 * @throws IOException
	 * @category C4S21
	 * @param List
	 *            <Long> ideasID
	 * @return void
	 */

	public static void export(List<Long> ideasID) throws IOException {
		String[][] toBeExported = convertList2Array(ideasID);
		String path = System.getProperty("java.class.path").split(";")[0]
				.replace("conf", "") + "searchResults.csv";
		File file = new File(path);
		if (!file.exists())
			file.createNewFile();
		FileWriter writer = new FileWriter(path, false);
		BufferedWriter out = new BufferedWriter(writer);
		if (toBeExported != null)
			for (int i = 0; i < toBeExported.length; i++) {
				for (int j = 0; j < toBeExported[i].length; j++)
					out.append(toBeExported[i][j] + ",");
				out.newLine();
			}
		else {
			out.append("No results found");
			out.close();
		}
		out.close();
		render(path);
	}

	/**
	 * Helper method used to convert List<long> to String [][]
	 * 
	 * @author Nader Alexan
	 * @version 2010.0505
	 * @param ideas
	 * @return String [][]
	 */

	public static String[][] convertList2Array(List<Long> ideas) {
		if (ideas == null)
			return null;
		int length = ((Idea) Idea.findById(ideas.get(0))).toArray().length;
		String[][] result = new String[ideas.size()][length];
		for (int i = 0; i < ideas.size(); i++)
			result[i] = ((Idea) Idea.findById(ideas.get(i))).toArray();
		return result;
	}

}
